﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TiposComuns.Objectos;
using Servidor.Objectos.Pesquisa;

namespace Servidor.Objectos
{
    /// <summary>
    /// This class holds all the information of a particular user, hosted in the server
    /// </summary>
    [Serializable]
    public class User
    {
        #region Attributes
        private Friends friends;            //Friends accepted or pendent
        private Wall wall;                  //Wall with all the messages related to the user
        private Profile profile;            //User's profile
        private Person person;             //User's address (uri and port) and username

        private KTree searchTree;                   //Auxiliar tree for the kademlia
        private SearchedNodes searched;             //Map between properties's keys and persons that have it

        public KTree SearchTree
        {
            get { return searchTree; }
            set { searchTree = value; }
        }

        public SearchedNodes Searched
        {
            get { return searched; }
            set { searched = value; }
        }
        #endregion

        #region Constructors
        public User()
        {
            this.friends = new Friends();
            this.wall = new Wall();
            this.searched = new SearchedNodes();
            this.searchTree = new KTree();
            this.person = new Person();
        }

        public User(Friends friends, Wall wall, Profile profile, Person person)
        {
            this.friends = friends;
            this.wall = wall;
            this.profile = profile;
            this.person = person;
            this.searchTree = new KTree(person);
            this.searched = new SearchedNodes();
        }
        #endregion

        #region Modifiers
        public Person Person
        {
            get { return person; }
            set { person = value; }
        }

        public Profile Perfil
        {
            get { return profile; }
            set { profile = value; }
        }
        
        public Wall Wall
        {
            get { return wall; }
            set { wall = value; }
        }
        
        public Friends Friends
        {
            get { return friends; }
            set { friends = value; }
        }
        #endregion

        #region Methods

        #region Friends

        /// <summary>
        /// Accepts a friend, removing him from the pendent lists of sent and received requests
        /// </summary>
        /// <param name="id">Message identifier</param>
        /// <param name="friend">New friend</param>
        public void AcceptFriend(NewFriendPost post)
        {
            this.friends.AcceptFriend(post.Requester);
            this.wall.Post((Post)post);
        }

        /// <summary>
        /// Adds person to the sent list
        /// </summary>
        /// <param name="friend">Target of the request</param>
        public void RequestFriend(Person friend)
        {
            this.friends.RequestFriend(friend);
        }

        /// <summary>
        /// Receive request from a remote user
        /// </summary>
        /// <param name="friend">Requester</param>
        public void ReceiveFriend(Person friend)
        {
            this.friends.ReceiveFriend(friend);
        }

        /// <summary>
        /// Rejects a friend request
        /// </summary>
        /// <param name="friend">Rejected friend</param>
        public void RejectFriend(Person friend)
        {
            this.friends.RejectFriend(friend);
        }

        /// <summary>
        /// Removes a friend
        /// </summary>
        /// <param name="friend">Removed friend</param>
        public void RemoveFriend(Person friend)
        {
            this.friends.RemoveFriend(friend);
        }

        /// <summary>
        /// Gets all the friends
        /// </summary>
        /// <returns>Friends</returns>
        public List<Person> GetFriends()
        {
            return friends.ListFriends();
        }

        public List<Person> GetFriendsReceived()
        {
            return friends.ReceivedRequests();
        }

        public List<Person> GetFriendsSent()
        {
            return friends.SentRequests();
        }

        #endregion

        #region Message posts

        public bool MayAddFriend(Person friend)
        {
            return this.friends.MayAdd(friend);
        }
        /// <summary>
        /// Post a new message in the wall
        /// </summary>
        /// <param name="post"></param>
        public void PostMessage(Post post)
        {
            this.wall.Post(post);
        }

        public List<Post> GetPosts()
        {
            return this.wall.Posts;
        }

        /// <summary>
        /// Returns a map between a friend's username and the last
        /// post received from him.
        /// </summary>
        /// <returns>Map between username and identifier of the last post</returns>
        public Dictionary<string,IDMsg> GetLastReceivedPosts()
        {
            return this.wall.GetUsers();
        }

        /// <summary>
        /// Get last posts
        /// </summary>
        /// <param name="last"> Identifier of the last sent post</param>
        /// <returns>List of recent posts</returns>
        public List<Post> PostsSince(int last)
        {
            return this.wall.GetAfter(last);
        }

        /// <summary>
        /// Post all the messages
        /// </summary>
        /// <param name="posts">List of messages</param>
        public void PostAll(List<Post> posts)
        {
            this.wall.PostAll(posts);
        }

        #endregion

        #region Profile

        public void UpdateProfile(Profile profile)
        {
            this.profile = profile;
        }
        #endregion

        #endregion
    }
}
